package demoMod.nanaki;

import basemod.AutoAdd;
import basemod.BaseMod;
import basemod.ModPanel;
import basemod.helpers.RelicType;
import basemod.interfaces.*;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.evacipated.cardcrawl.modthespire.Loader;
import com.evacipated.cardcrawl.modthespire.lib.SpireConfig;
import com.evacipated.cardcrawl.modthespire.lib.SpireInitializer;
import com.google.gson.Gson;
import com.megacrit.cardcrawl.actions.AbstractGameAction;
import com.megacrit.cardcrawl.characters.AbstractPlayer;
import com.megacrit.cardcrawl.core.Settings;
import com.megacrit.cardcrawl.helpers.CardHelper;
import com.megacrit.cardcrawl.helpers.ImageMaster;
import com.megacrit.cardcrawl.localization.*;
import com.megacrit.cardcrawl.relics.AbstractRelic;
import demoMod.nanaki.cards.nanaki.AbstractNanakiCard;
import demoMod.nanaki.cards.tempCards.AbstractBlessingCard;
import demoMod.nanaki.cards.tempCards.Syllable;
import demoMod.nanaki.characters.NanakiCharacter;
import demoMod.nanaki.dynamicVariables.MiscNumber;
import demoMod.nanaki.patches.AbstractCardEnum;
import demoMod.nanaki.patches.AbstractPlayerEnum;
import demoMod.nanaki.patches.CharacterSelectScreenPatch;
import demoMod.nanaki.potions.GramoBottle;
import demoMod.nanaki.potions.Mace;
import demoMod.nanaki.potions.ThroatSpray;
import demoMod.nanaki.relics.*;

import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;

@SpireInitializer
public class NanakiMod implements EditStringsSubscriber,
        EditRelicsSubscriber,
        PostUpdateSubscriber,
        PostRenderSubscriber,
        EditCardsSubscriber,
        PostInitializeSubscriber,
        StartGameSubscriber,
        StartActSubscriber,
        PostDungeonInitializeSubscriber,
        EditCharactersSubscriber,
        EditKeywordsSubscriber,
        AddAudioSubscriber {
    //攻击、技能、能力牌的图片(512)
    private static final String ATTACK_CC = getResourcePath("512/bg_attack.png");
    private static final String SKILL_CC = getResourcePath("512/bg_skill.png");
    private static final String POWER_CC = getResourcePath("512/bg_power.png");
    private static final String ATTACK_BLESS = getResourcePath("512/bg_bless_attack.png");
    private static final String SKILL_BLESS = getResourcePath("512/bg_bless_skill.png");
    private static final String POWER_BLESS = getResourcePath("512/bg_bless_power.png");
    private static final String ENERGY_ORB_CC = getResourcePath("512/Orb.png");
    //攻击、技能、能力牌的图片(1024)
    private static final String ATTACK_CC_PORTRAIT = getResourcePath("1024/bg_attack.png");
    private static final String SKILL_CC_PORTRAIT = getResourcePath("1024/bg_skill.png");
    private static final String POWER_CC_PORTRAIT = getResourcePath("1024/bg_power.png");
    private static final String ATTACK_BLESS_PORTRAIT = getResourcePath("1024/bg_bless_attack.png");
    private static final String SKILL_BLESS_PORTRAIT = getResourcePath("1024/bg_bless_skill.png");
    private static final String POWER_BLESS_PORTRAIT = getResourcePath("1024/bg_bless_power.png");
    private static final String ENERGY_ORB_CC_PORTRAIT = getResourcePath("1024/Orb.png");
    public static final String CARD_ENERGY_ORB = getResourcePath("UI/Orb.png");
    //选英雄界面的角色图标、选英雄时的背景图片
    private static final String MY_CHARACTER_BUTTON = getResourcePath("charSelect/Button.png");
    private static final String NANAKI_PORTRAIT = getResourcePath("charSelect/Portrait.png");

    private static final List<AbstractGameAction> actionList = new ArrayList<>();
    private static AbstractGameAction currentAction;
    private static final List<AbstractGameAction> parallelActionList = new ArrayList<>();
    public static final Color GREYN = CardHelper.getColor(134, 223, 181);
    public static boolean isReskinUnlocked = false;
    public static SpireConfig reskinSaveData;

    static {
        try {
            reskinSaveData = new SpireConfig("Nanaki", "reskinSaveData");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void initialize() {
        new NanakiMod();
        BaseMod.addColor(AbstractCardEnum.NANAKI,
                GREYN, GREYN, GREYN, GREYN,
                GREYN, GREYN, GREYN,
                ATTACK_CC, SKILL_CC, POWER_CC, ENERGY_ORB_CC,
                ATTACK_CC_PORTRAIT, SKILL_CC_PORTRAIT, POWER_CC_PORTRAIT,
                ENERGY_ORB_CC_PORTRAIT, CARD_ENERGY_ORB);
        BaseMod.addColor(AbstractCardEnum.BLESSING,
                GREYN, GREYN, GREYN, GREYN,
                GREYN, GREYN, GREYN,
                ATTACK_BLESS, SKILL_BLESS, POWER_BLESS, ENERGY_ORB_CC,
                ATTACK_BLESS_PORTRAIT, SKILL_BLESS_PORTRAIT, POWER_BLESS_PORTRAIT,
                ENERGY_ORB_CC_PORTRAIT, CARD_ENERGY_ORB);
    }

    public NanakiMod() {
        BaseMod.subscribe(this);
    }

    public static String makeID(String name) {
        return "Nanaki:" + name;
    }

    public static String getResourcePath(String path) {
        return "NanakiImages/" + path;
    }

    public static String getLanguageString() {
        String language;
        switch (Settings.language) {
            case ZHS:
                language = "zhs";
                break;
                /*
            case KOR:
                language = "kor";
                break;
            case JPN:
                language = "jpn";
                break;
                */
            default:
                language = "eng";
        }
        return language;
    }

    @Override
    public void receiveAddAudio() {
        BaseMod.addAudio("STROPHE_1_ENTER", "NanakiAudios/sfx/poemBg/poem1(enter).wav");
        BaseMod.addAudio("STROPHE_1_INTRO", "NanakiAudios/sfx/poemBg/intro/poem1.wav");
        BaseMod.addAudio("STROPHE_1_LOOP", "NanakiAudios/sfx/poemBg/loop/poem1.wav");

        BaseMod.addAudio("STROPHE_2_ENTER", "NanakiAudios/sfx/poemBg/poem2(enter).wav");
        BaseMod.addAudio("STROPHE_2_INTRO", "NanakiAudios/sfx/poemBg/intro/poem2.wav");
        BaseMod.addAudio("STROPHE_2_LOOP", "NanakiAudios/sfx/poemBg/loop/poem2.wav");

        BaseMod.addAudio("STROPHE_3_ENTER", "NanakiAudios/sfx/poemBg/poem3(enter).wav");
        BaseMod.addAudio("STROPHE_3_INTRO", "NanakiAudios/sfx/poemBg/intro/poem3.wav");
        BaseMod.addAudio("STROPHE_3_LOOP", "NanakiAudios/sfx/poemBg/loop/poem3.wav");

        BaseMod.addAudio("STROPHE_3_EXIT", "NanakiAudios/sfx/poemBg/poem3(exit).wav");
        BaseMod.addAudio("SFX_HERALD_DAWN", "NanakiAudios/sfx/HeraldDawn.wav");
    }

    @Override
    public void receiveEditCards() {
        BaseMod.addDynamicVariable(new MiscNumber());
        new AutoAdd("Nanaki")
                .packageFilter(AbstractNanakiCard.class)
                .setDefaultSeen(true)
                .cards();
        new AutoAdd("Nanaki")
                .packageFilter(AbstractBlessingCard.class)
                .setDefaultSeen(true)
                .cards();
        BaseMod.addCard(new Syllable());
    }

    @Override
    public void receiveEditCharacters() {
        BaseMod.addCharacter(new NanakiCharacter("Nanaki"), MY_CHARACTER_BUTTON, NANAKI_PORTRAIT, AbstractPlayerEnum.NANAKI);
    }

    @Override
    public void receiveEditKeywords() {
        final Gson gson = new Gson();
        String language;
        language = getLanguageString();
        final String json = Gdx.files.internal("localizations/" + language + "/Nanaki-KeywordStrings.json").readString(String.valueOf(StandardCharsets.UTF_8));
        com.evacipated.cardcrawl.mod.stslib.Keyword[] keywords = gson.fromJson(json, com.evacipated.cardcrawl.mod.stslib.Keyword[].class);
        if (keywords != null) {
            for (com.evacipated.cardcrawl.mod.stslib.Keyword keyword : keywords) {
                BaseMod.addKeyword("nnk", keyword.PROPER_NAME, keyword.NAMES, keyword.DESCRIPTION);
            }
        }
    }

    @Override
    public void receiveEditRelics() {
        BaseMod.addRelicToCustomPool(new TheBell(), AbstractCardEnum.NANAKI);
        BaseMod.addRelicToCustomPool(new SoulCallingSong(), AbstractCardEnum.NANAKI);
        BaseMod.addRelicToCustomPool(new SpellBottle(), AbstractCardEnum.NANAKI);
        BaseMod.addRelicToCustomPool(new OldHeadwear(), AbstractCardEnum.NANAKI);
        BaseMod.addRelicToCustomPool(new MidasTouch(), AbstractCardEnum.NANAKI);
        BaseMod.addRelicToCustomPool(new PersonalLetter(), AbstractCardEnum.NANAKI);
        BaseMod.addRelic(new StareyeHat(), RelicType.SHARED);
        BaseMod.addRelicToCustomPool(new Vine(), AbstractCardEnum.NANAKI);
        BaseMod.addRelicToCustomPool(new TheHalo(), AbstractCardEnum.NANAKI);
        BaseMod.addRelicToCustomPool(new Preempt3000(), AbstractCardEnum.NANAKI);
    }

    @Override
    public void receiveEditStrings() {
        String language = Settings.language.name().toLowerCase(Locale.ROOT);
        String uiStrings = Gdx.files.internal("localizations/" + language + "/Nanaki-UIStrings.json").readString("UTF-8");
        BaseMod.loadCustomStrings(UIStrings.class, uiStrings);
        String cardStrings = Gdx.files.internal("localizations/" + language + "/Nanaki-CardStrings.json").readString("UTF-8");
        BaseMod.loadCustomStrings(CardStrings.class, cardStrings);
        String powerStrings = Gdx.files.internal("localizations/" + language + "/Nanaki-PowerStrings.json").readString("UTF-8");
        BaseMod.loadCustomStrings(PowerStrings.class, powerStrings);
        String potionStrings = Gdx.files.internal("localizations/" + language + "/Nanaki-PotionStrings.json").readString("UTF-8");
        BaseMod.loadCustomStrings(PotionStrings.class, potionStrings);
        String charStrings = Gdx.files.internal("localizations/" + language + "/Nanaki-CharacterStrings.json").readString("UTF-8");
        BaseMod.loadCustomStrings(CharacterStrings.class, charStrings);
        String relicStrings = Gdx.files.internal("localizations/" + language + "/Nanaki-RelicStrings.json").readString("UTF-8");
        BaseMod.loadCustomStrings(RelicStrings.class, relicStrings);
        String stanceStrings = Gdx.files.internal("localizations/" + language + "/Nanaki-StanceStrings.json").readString("UTF-8");
        BaseMod.loadCustomStrings(StanceStrings.class, stanceStrings);
        String eventStrings = Gdx.files.internal("localizations/" + language + "/Nanaki-EventStrings.json").readString("UTF-8");
        BaseMod.loadCustomStrings(EventStrings.class, eventStrings);
    }

    @Override
    public void receivePostDungeonInitialize() {

    }

    @Override
    public void receivePostInitialize() {
        try {
            reskinSaveData.load();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (reskinSaveData.has("reskinIndex")) {
            CharacterSelectScreenPatch.reskinIndex = reskinSaveData.getInt("reskinIndex");
        }
        if (reskinSaveData.has("isReskinUnlocked")) {
            isReskinUnlocked = reskinSaveData.getBool("isReskinUnlocked");
        }
        ModPanel settingsPanel = new ModPanel();
        Texture badgeTexture = ImageMaster.loadImage(getResourcePath("UI/badge.png"));
        BaseMod.registerModBadge(badgeTexture, "Nanaki", "Temple9", "todo", settingsPanel);

        BaseMod.addPotion(Mace.class, new Color(0.58F, 0.24F, 0.71F, 1.0F), Color.PURPLE, null, Mace.ID, AbstractPlayerEnum.NANAKI);
        BaseMod.addPotion(ThroatSpray.class, new Color(0.525F, 0.874F, 0.71F, 1.0F), new Color(0.525F, 0.874F, 0.71F, 1.0F), null, ThroatSpray.ID, AbstractPlayerEnum.NANAKI);
        BaseMod.addPotion(GramoBottle.class, new Color(0.94F, 0.39F, 0.42F, 1.0F), new Color(0.94F, 0.39F, 0.42F, 1.0F), null, GramoBottle.ID, AbstractPlayerEnum.NANAKI);

        if (Loader.isModLoaded("IsaacModExtend")) {
            try {
                Class<?> clz = Class.forName("isaacModExtend.relics.Birthright");
                Field birthrightEffectsField = clz.getDeclaredField("birthrightEffects");
                Map<Class<? extends AbstractPlayer>, AbstractRelic> birthrightEffects = (Map<Class<? extends AbstractPlayer>, AbstractRelic>) birthrightEffectsField.get(null);
                birthrightEffects.put(NanakiCharacter.class, new NanakiBirthrightRelic());
            } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
    }

    @Override
    public void receivePostRender(SpriteBatch sb) {

    }

    @Override
    public void receivePostUpdate() {
        if (!actionList.isEmpty() && currentAction == null) {
            currentAction = actionList.remove(0);
        }
        if (currentAction != null) {
            currentAction.update();
            if (currentAction.isDone) {
                actionList.remove(currentAction);
                currentAction = null;
            }
        }
        if (!parallelActionList.isEmpty()) {
            for (AbstractGameAction action : parallelActionList) {
                action.update();
            }
            parallelActionList.removeIf(action -> action.isDone);
        }
    }

    public static void addToBot(AbstractGameAction action) {
        actionList.add(action);
    }

    public static void addToTop(AbstractGameAction action) {
        actionList.add(0, action);
    }

    public static void addToParallelBot(AbstractGameAction action) {
        parallelActionList.add(action);
    }

    public static void cancelAction(AbstractGameAction action) {
        actionList.remove(action);
        if (currentAction == action) {
            currentAction = null;
        }
    }

    @Override
    public void receiveStartAct() {

    }

    @Override
    public void receiveStartGame() {

    }
}
